<Serializable()> _
Public Class BaseDescriptor
    Implements System.ComponentModel.ICustomTypeDescriptor, ICloneable

    Public Class PropertyDescriptorComparer
        Implements IComparer

        Public Function Compare(ByVal x As Object, ByVal y As Object) As Integer Implements System.Collections.IComparer.Compare
            Dim intX As Integer = 0
            Dim intY As Integer = 0
            Dim objAttribute As Attribute
            Dim objPropertyDescriptorX As System.ComponentModel.PropertyDescriptor = CType(x, System.ComponentModel.PropertyDescriptor)
            Dim objPropertyDescriptorY As System.ComponentModel.PropertyDescriptor = CType(y, System.ComponentModel.PropertyDescriptor)

            objAttribute = objPropertyDescriptorX.Attributes(GetType(CustomOrder))
            If objAttribute IsNot Nothing Then intX = CType(objAttribute, CustomOrder).Order
            objAttribute = objPropertyDescriptorY.Attributes(GetType(CustomOrder))
            If objAttribute IsNot Nothing Then intY = CType(objAttribute, CustomOrder).Order

            Return intX.CompareTo(intY)
        End Function

    End Class

    Public Class CustomCategory
        Inherits System.ComponentModel.CategoryAttribute

        Public Sub New(ByVal key As String)
            MyBase.New(IIf(key.EndsWith("C"), "", "(" + key.Substring(key.IndexOf("C") + 1) + ") ").ToString + Language.ReadProperties(key))
        End Sub

    End Class

    Public Class CustomDescription
        Inherits System.ComponentModel.DescriptionAttribute

        Public Sub New(ByVal key As String)
            MyBase.New(Language.ReadProperties(key + "_Desc"))
        End Sub

    End Class

    Public Class CustomDisplayName
        Inherits System.ComponentModel.DisplayNameAttribute

        Public Sub New(ByVal key As String)
            MyBase.New(Language.ReadProperties(key + "_Name"))
        End Sub

    End Class

    Public Class CustomOrder
        Inherits System.Attribute

        Private m_intOrder As Integer

        Public Sub New(ByVal order As Integer)
            m_intOrder = order
        End Sub

        Public ReadOnly Property Order() As Integer
            Get
                Return m_intOrder
            End Get
        End Property

    End Class


    Public Function Clone() As Object Implements System.ICloneable.Clone
        Dim objBinaryFormatter As New System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
        Dim objMemoryStream As New System.IO.MemoryStream
        Dim objReturn As Object

        objBinaryFormatter.Serialize(objMemoryStream, Me)
        objMemoryStream.Position = 0
        objReturn = objBinaryFormatter.Deserialize(objMemoryStream)
        objMemoryStream.Close()

        Return objReturn
    End Function

    Public Function GetAttributes() As System.ComponentModel.AttributeCollection Implements System.ComponentModel.ICustomTypeDescriptor.GetAttributes
        Return System.ComponentModel.TypeDescriptor.GetAttributes(Me, True)
    End Function

    Public Function GetClassName() As String Implements System.ComponentModel.ICustomTypeDescriptor.GetClassName
        Return System.ComponentModel.TypeDescriptor.GetClassName(Me, True)
    End Function

    Public Function GetComponentName() As String Implements System.ComponentModel.ICustomTypeDescriptor.GetComponentName
        Return System.ComponentModel.TypeDescriptor.GetComponentName(Me, True)
    End Function

    Public Function GetConverter() As System.ComponentModel.TypeConverter Implements System.ComponentModel.ICustomTypeDescriptor.GetConverter
        Return System.ComponentModel.TypeDescriptor.GetConverter(Me, True)
    End Function

    Public Function GetDefaultEvent() As System.ComponentModel.EventDescriptor Implements System.ComponentModel.ICustomTypeDescriptor.GetDefaultEvent
        Return System.ComponentModel.TypeDescriptor.GetDefaultEvent(Me, True)
    End Function

    Public Function GetDefaultProperty() As System.ComponentModel.PropertyDescriptor Implements System.ComponentModel.ICustomTypeDescriptor.GetDefaultProperty
        Return System.ComponentModel.TypeDescriptor.GetDefaultProperty(Me, True)
    End Function

    Public Function GetEditor(ByVal editorBaseType As System.Type) As Object Implements System.ComponentModel.ICustomTypeDescriptor.GetEditor
        Return System.ComponentModel.TypeDescriptor.GetEditor(Me, editorBaseType, True)
    End Function

    Public Function GetEvents() As System.ComponentModel.EventDescriptorCollection Implements System.ComponentModel.ICustomTypeDescriptor.GetEvents
        Return System.ComponentModel.TypeDescriptor.GetEvents(Me, True)
    End Function

    Public Function GetEvents(ByVal attributes() As System.Attribute) As System.ComponentModel.EventDescriptorCollection Implements System.ComponentModel.ICustomTypeDescriptor.GetEvents
        Return System.ComponentModel.TypeDescriptor.GetEvents(Me, attributes, True)
    End Function

    Public Function GetProperties() As System.ComponentModel.PropertyDescriptorCollection Implements System.ComponentModel.ICustomTypeDescriptor.GetProperties
        Return System.ComponentModel.TypeDescriptor.GetProperties(Me, True).Sort(New PropertyDescriptorComparer)
    End Function

    Public Function GetProperties(ByVal attributes() As System.Attribute) As System.ComponentModel.PropertyDescriptorCollection Implements System.ComponentModel.ICustomTypeDescriptor.GetProperties
        Return System.ComponentModel.TypeDescriptor.GetProperties(Me, attributes, True).Sort(New PropertyDescriptorComparer)
    End Function

    Public Function GetPropertyOwner(ByVal pd As System.ComponentModel.PropertyDescriptor) As Object Implements System.ComponentModel.ICustomTypeDescriptor.GetPropertyOwner
        Return Me
    End Function

End Class
